from pydantic import BaseModel, HttpUrl, validator, Field
from datetime import datetime
from typing import Generic, TypeVar, Optional, List, Dict, Any
from pydantic import BaseModel, HttpUrl, validator, Field
from enum import IntEnum

from bot_api_v1.app.utils.media_extrat_format import Media_extract_format
from bot_api_v1.app.constants.media_info import MediaPlatform
from bot_api_v1.app.core.logger import logger


from bot_api_v1.app.constants.media_info import MediaType
# 先定义类型变量T，然后才能在BaseResponse中使用
T = TypeVar('T')

# 错误码定义
class ErrorCode(IntEnum):
    SUCCESS = 200
    BAD_REQUEST = 400
    UNAUTHORIZED = 401
    FORBIDDEN = 403
    NOT_FOUND = 404
    INTERNAL_ERROR = 500

class BaseResponse(BaseModel, Generic[T]):
    code: int = Field(default=ErrorCode.SUCCESS, example=200, 
                     description="遵循HTTP状态码规范")
    message: str = Field(default="success", example="操作成功",
                       min_length=2, max_length=255)
    data: Optional[T] = Field(default=None, 
                              description="业务数据载荷")
    timestamp: datetime = Field(default_factory=datetime.now,
                               example="2024-05-28T10:30:45.123Z")
    
    class Config:
        json_encoders = {
            datetime: lambda v: v.isoformat()
        }
        arbitrary_types_allowed = True

class PaginatedData(BaseModel):
    current_page: int = Field(ge=1, example=1)
    page_size: int = Field(ge=1, le=100, example=10)
    total_items: int = Field(ge=0, example=100)
    total_pages: int = Field(ge=0, example=10)
    items: list = Field(default_factory=list)


class PaginatedResponse(BaseResponse[PaginatedData]):
    pass


class MediaAuthor(BaseModel):
    id: str = Field(..., description="作者ID")
    sec_uid: str = Field(..., description="作者安全ID/唯一标识")
    nickname: str = Field(..., description="作者昵称")
    avatar: Optional[str] = Field(None, description="头像URL")
    signature: Optional[str] = Field(None, description="个人签名")
    verified: Optional[bool] = Field(None, description="是否认证")
    follower_count: Optional[int] = Field(None, description="粉丝数")
    following_count: Optional[int] = Field(None, description="关注数")
    region: Optional[str] = Field(None, description="地区")


class MediaStatistics(BaseModel):
    like_count: Optional[int] = Field(None, description="点赞数")
    comment_count: Optional[int] = Field(None, description="评论数")
    share_count: Optional[int] = Field(None, description="分享数")
    collect_count: Optional[int] = Field(None, description="收藏数")
    play_count: Optional[int] = Field(None, description="播放数")


class Points(BaseModel):
    total_required: Optional[int] = Field(None, description="消耗积分数")
    user_available_points: Optional[int] = Field(None, description="剩余积分数")


class AIASSITENT(BaseModel):
    core: Optional[str] = Field(None, description="文案核心")
    formula: Optional[str] = Field(None, description="文案爆款公式")
    golden3s: Optional[str] = Field(None, description="文案黄金三秒")
    copywriting: Optional[str] = Field(None, description="小红书文案")


class MediaInfo(BaseModel):
    cover_url: Optional[str] = Field(None, description="封面URL")
    video_url: Optional[str] = Field(None, description="视频URL")
    duration: Optional[int] = Field(None, description="视频时长(秒)")
    width: Optional[int] = Field(None, description="视频宽度")
    height: Optional[int] = Field(None, description="视频高度")
    quality: Optional[str] = Field(None, description="视频质量")


class RequestContext(BaseModel):
    trace_id: str = Field(..., description="请求跟踪ID")
    app_id: Optional[str] = Field(None, description="应用ID")
    source: Optional[str] = Field(None, description="请求来源")
    user_id: Optional[str] = Field(None, description="用户ID")
    user_name: Optional[str] = Field(None, description="用户名")
    ip: Optional[str] = Field(None, description="客户端IP")
    timestamp: datetime = Field(..., description="请求时间")


class MediaContentResponse(BaseModel):
    platform: str = Field(..., description="平台名称 (douyin, xiaohongshu)")
    video_id: str = Field(..., description="视频ID")
    original_url: str = Field(..., description="原始URL")
    title: Optional[str] = Field(None, description="视频标题")
    description: Optional[str] = Field(None, description="视频描述")
    content: Optional[str] = Field(None, description="视频文案内容")
    tags: List[str] = Field(default_factory=list, description="标签列表")
    author: MediaAuthor = Field(..., description="作者信息")
    statistics: MediaStatistics = Field(..., description="统计信息")
    media: MediaInfo = Field(..., description="媒体信息")
    ai_assistant_text: AIASSITENT = Field(..., description="AI助手生成的文案")
    points: Points = Field(..., description="用户积分信息")
    publish_time: Optional[datetime] = Field(None, description="发布时间")
    update_time: Optional[datetime] = Field(None, description="更新时间")

    # 新增字段
    # comments_summary: Optional[Dict[str, Any]] = Field(None, description="评论摘要，如高赞评论、词云数据")
    # # comment_details: Optional[List[CommentInfo]] = Field(None, description="评论详情列表（可能数据量大，酌情返回）")
    # comparison_with_author_videos: Optional[VideoComparisonStats] = Field(None, description="与同作者其他视频的比较统计")
    # daily_growth_stats: Optional[VideoGrowthStats] = Field(None, description="日增长统计")
    # weekly_growth_stats: Optional[VideoGrowthStats] = Field(None, description="周增长统计")


class MediaBasicContentResponse(BaseModel):
    platform: str = Field(..., description="平台名称 (douyin, xiaohongshu)")
    video_id: str = Field(..., description="视频ID")
    original_url: str = Field(..., description="原始URL")
    title: Optional[str] = Field(None, description="视频标题")
    description: Optional[str] = Field(None, description="视频描述")
    content: Optional[str] = Field(None, description="视频文案内容")
    tags: List[str] = Field(default_factory=list, description="标签列表")
    author: MediaAuthor = Field(..., description="作者信息")
    statistics: MediaStatistics = Field(..., description="统计信息")
    media: MediaInfo = Field(..., description="媒体信息")
    # ai_assistant_text: AIASSITENT = Field(..., description="AI助手生成的文案")
    # points: Points = Field(..., description="用户积分信息")
    publish_time: Optional[datetime] = Field(None, description="发布时间")
    update_time: Optional[datetime] = Field(None, description="更新时间")


class MediaExtractResponse(BaseResponse[MediaContentResponse]):
    request_context: Optional[RequestContext] = Field(None, description="请求上下文信息")


# --- 请求与响应模型 ---

class MediaExtractRequest(BaseModel):
    """媒体内容提取请求模型"""
    url: HttpUrl = Field(..., description="媒体URL地址")
    extract_text: bool = Field(True, description="是否提取文案内容")
    include_comments: bool = Field(False, description="是否包含评论数据")

    @validator('url')
    def validate_url(cls, v):
        if not str(v).startswith(('http://', 'https://')):
            raise ValueError('必须是有效的HTTP或HTTPS URL')
        return str(v)


class MediaExtractSubmitResponse(BaseModel):
    """提交异步提取任务后的响应模型"""
    code: int = 202
    message: str
    task_id: str
    root_trace_key: str
    request_context: RequestContext


class MediaExtractResponse(BaseModel): # 复用或重命名旧的响应模型
    """提取媒体内容（同步或完成后）的响应模型"""
    code: int = 200
    message: str
    data: Optional[MediaContentResponse] = None # MediaContentResponse 需已定义
    request_context: RequestContext


class MediaExtractBasicContentResponse(BaseModel): # 复用或重命名旧的响应模型
    """提取媒体内容（同步或完成后）的响应模型"""
    code: int = 200
    message: str
    data: Optional[MediaBasicContentResponse] = None # MediaContentResponse 需已定义
    request_context: RequestContext


class MediaExtractStatusResponse(BaseModel):
    """查询异步提取任务状态的响应模型"""
    code: int
    message: str
    task_id: str
    root_trace_key: str
    status: str # PENDING, running, completed, failed, cancelled, ...
    result: Optional[MediaContentResponse] = None # 任务成功时的结果
    data: Optional[MediaContentResponse] = None # MediaContentResponse 需已定义
    error: Optional[str] = None # 任务失败时的错误信息
    request_context: RequestContext


class SearchNoteRequest(BaseModel):
    platform: str
    query: str
    num: int = 10
    qsort: str = "general"

class AuthorInfo(BaseModel): #
    id: str = ""  # 对应 user_id
    sec_uid: Optional[str] = "" # API示例中未提供，设为可选或默认空
    nickname: str = "" #
    avatar: Optional[HttpUrl | str] = "" # API提供的是字符串，可以是HttpUrl类型
    signature: Optional[str] = "" # API示例中未提供
    verified: Optional[bool] = False # API示例中未提供
    follower_count: Optional[int] = 0 # API示例中未提供
    following_count: Optional[int] = 0 # API示例中未提供
    total_likes_collections_count: Optional[int] = 0 # API示例中未提供
    total_post_count: Optional[int] = 0 # API示例中未提供
    region: Optional[str] = "" # API示例中未提供
    url: Optional[HttpUrl | str] = "" # 用户主页链接, API示例中未提供，可能需拼接



class SearchNoteData(BaseModel):
    title: str = ""
    platform: str = ""
    description: str = ""
    publish_time: Optional[datetime] = None # 改为可选，默认值为 None
    play_count: int = 0
    like_count: int = 0
    comment_count: int = 0
    share_count: int = 0
    collect_count: int = 0
    author: Optional[AuthorInfo] = None # 保持 Optional，默认值为 None
    tags: str = ""
    video_platform_url: str = ""
    duration: int = 0
    video_id: str = ""
    video_url: str = ""
    cover_url: str = ""
    point_cost: int = 0


class SearchNoteResponse(BaseModel):
    code: int = 200
    message: str = "success"
    data: List[SearchNoteData] = []
    request_context: RequestContext


class KOLResponse(BaseModel):
    code: int = 200
    message: str = "success"
    data: Dict[str, Any] = {}
    request_context: RequestContext





class KOLPostData(BaseModel):
    note_id: str = Field(..., description="作品/笔记的唯一ID")
    title: Optional[str] = Field(None, description="标题或描述文案")
    platform: str = Field(..., description="来源平台 (例如：douyin, xiaohongshu)")
    media_type: str = Field(MediaType.UNKNOWN, description="媒体类型 (video, image)")
    
    cover_image_url: Optional[HttpUrl] = Field(None, description="封面图片URL")
    post_url: Optional[HttpUrl] = Field(None, description="作品/笔记的原始URL (如果可构建)")

    author_id: Optional[str] = Field(None, description="作者的唯一ID")
    author_nickname: Optional[str] = Field(None, description="作者昵称")
    author_avatar_url: Optional[HttpUrl] = Field(None, description="作者头像URL")

    create_time: Optional[datetime] = Field(None, description="发布时间 (UTC)")
    
    # 视频相关
    video_url: Optional[HttpUrl] = Field(None, description="视频播放地址 (如果类型是video)")
    video_duration: Optional[float] = Field(None, description="视频时长 (秒) (如果类型是video)")

    # 图文相关
    image_urls: Optional[List[HttpUrl]] = Field(None, description="图片URL列表 (如果类型是image)")

    # 可选的互动数据 (根据需要添加)
    like_count: Optional[int] = Field(None, description="点赞数")
    comment_count: Optional[int] = Field(None, description="评论数")
    collect_count: Optional[int] = Field(None, description="收藏数")
    share_count: Optional[int] = Field(None, description="分享数")

    # raw_data: Dict[str, Any] = Field(..., description="原始平台数据，用于调试或未来扩展")



class KOLPostResponse(BaseModel):
    code: int = 200
    message: str = "success"
    data: List[KOLPostData]  = []
    request_context: RequestContext





def create_douyin_schema(
    platform: str,
    basic_info: dict,
    url: str,
    transcribed_text: str,
    audio_duration: int,
    ai_assistent_content : dict,
    points : dict
):
    media_extract_format = Media_extract_format()
    basic_info = basic_info.get("data", {})  # 提取 video 字段
    info = {
        "platform": platform,
        "video_id": basic_info.get("id", ""),  # 使用 id 字段
        "original_url": url,
        "title": basic_info.get("desc", ""),
        "description": basic_info.get("desc", ""),
        "content": transcribed_text,
        "tags": media_extract_format._extract_tags_from_douyin(basic_info),
        
        "author": {
            "id": basic_info.get("uid", ""),  # 直接从顶层获取
            "sec_uid": basic_info.get("sec_uid", ""),  # 直接从顶层获取
            "nickname": basic_info.get("nickname", ""),  # 直接从顶层获取
            "avatar": "",  # 视频信息中可能没有头像URL
            "signature": basic_info.get("signature", ""),  # 直接从顶层获取
            "verified": False,  # 默认为False
            "follower_count": 0,  # 视频信息中可能没有粉丝数
            "following_count": 0,  # 视频信息中可能没有关注数
            "region": ""  # 视频信息中可能没有地区信息
        },
        
        "statistics": {
            "like_count": basic_info.get("digg_count", 0),  # 直接从顶层获取
            "comment_count": basic_info.get("comment_count", 0),  # 直接从顶层获取
            "share_count": basic_info.get("share_count", 0),  # 直接从顶层获取
            "collect_count": basic_info.get("collect_count", 0),  # 直接从顶层获取
            "play_count": basic_info.get("play_count", 0)  # 直接从顶层获取
        },
        
        "media": {
            "cover_url": basic_info.get("origin_cover", ""),  # 使用原始封面
            "video_url": basic_info.get("downloads", ""),  # 使用下载链接
            "duration": round(audio_duration) if audio_duration is not None else 0, # <<< 使用 round() 转换
            "width": basic_info.get("width", 0),  # 直接从顶层获取
            "height": basic_info.get("height", 0),  # 直接从顶层获取
            "quality": "normal"
        },
        "ai_assistant_text": ai_assistent_content,
        "points": points,
        
        "publish_time": media_extract_format._format_timestamp(basic_info.get("create_timestamp", 0)),
        "update_time": None
    }

    return info


def create_xhs_schema(
    platform: str,
    basic_info: dict,
    url: str,
    transcribed_text: str,
    audio_duration: int,
    ai_assistent_content : dict,
    points : dict
):
    media_extract_format = Media_extract_format()
    info = {
        "platform": platform,
        "video_id": basic_info.get("note_id", ""),
        "original_url": url,
        "title": basic_info.get("title", ""),
        "description": basic_info.get("desc", ""),
        "content": transcribed_text,
        "tags": basic_info.get("tags", []),
        
        "author": {
            "id": basic_info.get("author", {}).get("id", ""),
            "sec_uid": basic_info.get("author", {}).get("user_id", ""),
            "nickname": basic_info.get("author", {}).get("nickname", ""),
            "avatar": basic_info.get("author", {}).get("avatar", ""),
            "signature": basic_info.get("author", {}).get("signature", ""),
            "verified": basic_info.get("author", {}).get("verified", False),
            "follower_count": basic_info.get("author", {}).get("follower_count", 0),
            "following_count": basic_info.get("author", {}).get("following_count", 0),
            "region": basic_info.get("author", {}).get("location", "")
        },
        
        "statistics": {
            "like_count": basic_info.get("statistics", {}).get("like_count", 0),
            "comment_count": basic_info.get("statistics", {}).get("comment_count", 0),
            "share_count": basic_info.get("statistics", {}).get("share_count", 0),
            "collect_count": basic_info.get("statistics", {}).get("collected_count", 0),
            "play_count": basic_info.get("statistics", {}).get("view_count", 0)
        },
        
        "media": {
            "cover_url": basic_info.get("media", {}).get("cover_url", ""),
            "video_url": basic_info.get("media", {}).get("video_url", ""),
            "duration": round(audio_duration) if audio_duration is not None else 0, # <<< 使用 round() 转换
            "width": basic_info.get("media", {}).get("width", 0),
            "height": basic_info.get("media", {}).get("height", 0),
            "quality": "normal"
        },
        "ai_assistant_text": ai_assistent_content,
        "points": points,

        "publish_time": media_extract_format._format_timestamp(basic_info.get("create_time", 0)),
        "update_time": media_extract_format._format_timestamp(basic_info.get("last_update_time", 0))
    }

    return info

def create_default_schema(
    basic_info: dict,
    transcribed_text: str,
    ai_assistent_content : dict,
    points : dict):
    info = basic_info.copy()
    info["content"] = transcribed_text
    info["ai_assistant_text"] = ai_assistent_content
    info["points"] = points
    
    logger.debug(f"create_default_schema -- transcribed_text is : {transcribed_text}")
    logger.debug(f"create_default_schema -- ai_assistent_content is : {ai_assistent_content}")
    logger.debug(f"create_default_schema -- points is : {points}")

    return info

def create_bl_schema(
    basic_info: dict,
    transcribed_text: str,
    ai_assistent_content : dict,
    points : dict):
    return create_default_schema(basic_info, transcribed_text,ai_assistent_content,points)


def create_ks_schema(
    basic_info: dict,
    transcribed_text: str,
    ai_assistent_content : dict,
    points : dict):
    return create_default_schema(basic_info, transcribed_text,ai_assistent_content,points)

def create_schema(
    task_id: str,
    basic_info: dict,
    platform: str,
    url: str,
    transcribed_text: str,
    log_extra: dict,
    audio_duration: int,
    ai_assistent_content : dict,
    points : dict
):
    if platform == MediaPlatform.DOUYIN:
        # 转换为统一结构
        final_standard_data = create_douyin_schema(platform, basic_info, url, transcribed_text, audio_duration,ai_assistent_content,points)
    elif platform == MediaPlatform.XIAOHONGSHU:
        final_standard_data = create_xhs_schema(platform, basic_info, url, transcribed_text,audio_duration,ai_assistent_content,points)
    elif platform == MediaPlatform.BILIBILI:
        final_standard_data = create_bl_schema( basic_info, transcribed_text,ai_assistent_content,points)
    elif platform == MediaPlatform.KUAISHOU:
        final_standard_data = create_ks_schema( basic_info, transcribed_text,ai_assistent_content,points)
    else:
        # logger.error(f"[Task B {task_id=}] 未知的平台: {platform}", extra=log_extra)
        final_standard_data = create_default_schema( basic_info, transcribed_text,ai_assistent_content,points)

    return final_standard_data

